线程(Thread)
Scripting 的 UI 渲染系统以及绝大多数 JavaScript 执行逻辑默认运行在主线程中,因此通常开发者无需主动切换线程。
为了确保 UI 更新安全、避免主线程阻塞,并在必要时执行后台任务,Scripting 提供了全局 Thread API。部分系统 API 或运行时逻辑可能会在后台执行,此 API 能帮助你安全地处理复杂场景。
Thread 为全局命名空间,无需导入即可使用。
Thread.isMainThread: boolean
指示当前 JavaScript 执行环境是否在主线程。
在大多数情况下此值为 true,但某些系统回调或内部任务可能会切换到后台线程。在需要进行 UI 更新时,可以通过此属性确认当前线程是否安全。
1if (Thread.isMainThread) {
2 console.log('当前在主线程')
3} else {
4 console.log('当前不在主线程')
5}
Thread.runInMain(execute: () => void): void
在主线程中执行指定的函数。
由于 JavaScript 默认运行在主线程,通常无需手动调用此方法。它主要用于以下情况:
- 某些系统 API 回调在后台线程触发,开发者需要确保 UI 更新在主线程执行
- 希望严格保证某段逻辑在主线程中执行
此方法不会返回值,也不会切回执行前的线程,仅保证同步在主线程执行。
1Thread.runInMain(() => {
2 title.value = 'Updated on main thread'
3})
Thread.runInBackground<T>(execute: () => T | Promise<T>): Promise<T>
在后台线程执行指定函数,并以 Promise 形式将结果切回到调用处所在的线程(通常是主线程)。
适用于:
- 计算密集型任务
- 大型数据处理
- 不希望阻塞 UI 的耗时操作
execute 可以返回值或 Promise。
1const sum = await Thread.runInBackground(() => {
2 let v = 0
3 for (let i = 0; i < 5_000_000; i++) v += i
4 return v
5})
6
7console.log('结果:', sum)
异步示例:
1const image = await Thread.runInBackground(async () => {
2 const raw = await loadImage()
3 return processImage(raw)
4})
5
6Thread.runInMain(() => {
7 setImage(image)
8})
异步 I/O 的自动线程切换行为
Scripting 中 大量异步 I/O 方法(包括文件、网络、数据库等)会自动在后台线程执行,无需开发者手动使用 runInBackground。
例如:
1const content = await FileManager.readAsString(path)
readAsString 会自动切换到后台线程执行文件读取操作,然后将结果以 Promise 的方式切回调用时所在的线程(通常是主线程)。
这意味着你可以放心地直接调用异步 API,而无需担心阻塞 UI。
只有同步方法会在主线程执行
例如:
1const content = FileManager.readAsStringSync(path)
同步方法不会切线程,会在主线程直接执行 I/O 操作。因此:
- 不建议在同步方法中处理大型文件或执行耗时操作
- 如果需要高性能且不阻塞 UI,应使用异步版本(如 readAsString)
使用建议
- JavaScript 默认在主线程运行,大部分场景不需要调用
runInMain
- 异步 I/O(如 FileManager.readAsString)已经自动在后台线程执行
- 仅在执行计算密集型任务或同步 I/O 时需要使用
runInBackground
- 如果某些系统 API 回调在后台线程中触发,可使用
runInMain 保证 UI 更新安全
- 不应在后台线程中直接访问 UI,应在后台任务完成后再回到主线程处理